<?php

namespace dousdk;

use commonsdk\Tools;
use commonsdk\Video_range;
use think\exception\HttpResponseException;

class AuthAppKuaishou {

    const URL_CONNECT = 'https://open.kuaishou.com/oauth2/connect';
    const URL_TOKEN = 'https://open.kuaishou.com/oauth2/access_token';
    const URL_USER_INFO = 'https://open.kuaishou.com/openapi/user_info';
    const URL_VIDEO_UPLOAD_START = 'https://open.douyin.com/openapi/photo/start_upload';
    const URL_VIDEO_UPLOAD = 'http://{endpoint}/api/upload';
    const URL_VIDEO_UPLOAD_PART_UPLOAD = 'http://{endpoint}/api/upload/fragment';
    const URL_VIDEO_UPLOAD_PART_COMPLETE = 'http://{endpoint}/api/upload/complete';
    const URL_VIDEO_CREATE = 'https://open.kuaishou.com/openapi/photo/publish';
    
    static public $scopes = [
        'user_info',//公开信息
        'user_video_publish',//创建视频
        'user_video_delete',//删除视频
        'user_video_info'//查询视频
    ];
    
    public $client_key;
    public $client_secret;

    public function __destruct() {
        
    }
    

    /**
     * 通过网页授权获取粉丝信息
     */
    public function getWebOauthInfo($redirects, $redirect = true): array {
        if (input('get.code') == "") {
            $oauthurl = self::buildConnectUrl($redirects);
            if ($redirect) {
                throw new HttpResponseException(redirect($oauthurl, 301));
            } else {
                throw new HttpResponseException(response("window.location.href='{$oauthurl}'"));
            }
        }
        if (($token_arr = $this->getTokenByCode(input('get.code')))) {
            $fansinfo = self::getAuthUserInfo($token_arr['access_token'], $token_arr['open_id']);
            $fansinfo['access_token'] = $token_arr['access_token'];
            return $fansinfo;
        }
    }

    //创建授权跳转链接  获取code
    public function buildConnectUrl($redirect = "") {
        $arr = [
            'app_id' => $this->client_key,
            'scope' => implode(',', self::$scopes),
            'redirect_uri' => $redirect,
            'response_type' => 'code',
            'state' => "",
        ];
        return self::URL_CONNECT . '?' . http_build_query($arr);
    }

    //获取token
    public function getTokenByCode($code) {
        $arr = [
            'app_id' => $this->client_key,
            'app_secret' => $this->client_secret,
            'code' => $code,
            'grant_type' => 'authorization_code',
        ];
        //echo self::URL_TOKEN . '?' . http_build_query($arr);
        $response = file_get_contents(self::URL_TOKEN . '?' . http_build_query($arr));
        $data = self::checkResponse($response);
        return $data;
    }

    public function getAuthUserInfo($access_token) {
        $arr = [
            'access_token' => $access_token,
            'app_id' => $this->client_key
        ];
        $response = file_get_contents(self::URL_USER_INFO . '?' . http_build_query($arr));
        $data = self::checkResponse($response);
        return $data;
    }

    //发布
    public function publishItem($authAccount, $authItem) {
        
        $upinfo=self::start_upload($authAccount['token'], $this->client_key);
        
        //大于10M用分片上传,否则用普通上传
         if ($authItem['size'] > 10000000) {
             $data = $this->uploadPart($authItem,$upinfo);
         } else {
            $data = $this->upload($authItem,$upinfo);
        }
        $query_arr = [
            'upload_token' => $upinfo['upload_token'],
             'app_id' => $this->client_key,
            'access_token' => $authAccount['token']
        ];
        $body = [
            'cover' => $video_id,
            'caption' => $authItem['text'],
            ];
        $response = Tools::httpPost(self::URL_VIDEO_CREATE . '?' . http_build_query($query_arr), $body);
        $data = self::checkResponse($response[1]);
        return $data;
    }
    
    //发起上传
    private function start_upload($access_token,$app_id)
    {
        $query_arr = [
             'app_id' => $app_id,
            'access_token' => $access_token,
        ];
        $response = Tools::httpPost(self::URL_VIDEO_UPLOAD_START . '?' . http_build_query($query_arr), "");
        $data = self::checkResponse($response);
        if($data['result']==1)
        {
            return $data;
        }
    }

    //普通上传
    private function upload($video,$upinfo) {
        $query_arr = [
            'upload_token' => $upinfo['upload_token'],
        ];
        $Video_range=new Video_range();
        $content = file_get_contents($video['path']);
        $body_arr = Tools::buildDouyinUploadData($content);
        
        $upload_url= str_replace("{endpoint}",$upinfo['endpoint'],self::URL_VIDEO_UPLOAD);
        $response = Tools::postUploadData($upload_url. '?' . http_build_query($query_arr),$body_arr['data'],0,['Content-Type:video/mp4;']);
        $data = self::checkResponse($response);
        return $data;
    }

    //分片上传
    private function uploadPart($video,$upinfo) {
        $part = 1;
        $part_size = 10000000;
        while ($part) {
            $start = ($part - 1) * $part_size;
            if ($start >= $video['size']) {
                break;
            }

            //如果剩余不足一个分片则一并上传
            $yu = $video['size'] - $start - $part_size;
            if ($yu < $part_size) {
                $part_size += $yu;
            }
            $content = Video_range::getPartData($video['path'], $start, $part_size);
            $body_arr = Tools::buildDouyinUploadData($content);

            $query_arr = [
                'upload_token' => $upinfo['upload_token'],
                'fragment_id' => $part,
            ];
            
 Tools::postUploadData(str_replace("{endpoint}",$upinfo['endpoint'],self::URL_VIDEO_UPLOAD_PART_UPLOAD). '?' . http_build_query($query_arr), $body_arr['data'],0,['Content-Type:video/mp4;']);
            $part++;
        }
        $query_arr = [
            'fragment_count' => $part,
             'upload_token' => $upinfo['upload_token']
        ];
        
        $response = Tools::http_post_json(str_replace("{endpoint}",$upinfo['endpoint'],self::URL_VIDEO_UPLOAD_PART_COMPLETE). '?' . http_build_query($query_arr));
        $data = self::checkResponse($response);
        return $data;
    }

    //检测并格式化抖音返回数据
    static public function checkResponse($response) {
        $arr = json_decode($response, 1);
        if (empty($arr))
            throw new \Exception('接口返回错误', 20000);
        return $arr;
    }

}
